package com.sc.nft.controller;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.sc.nft.annotation.UserLogin;
import com.sc.nft.controller.request.*;
import com.sc.nft.controller.vo.IsPledgeConditionsVO;
import com.sc.nft.dao.MerchantPledgeTaskConfDao;
import com.sc.nft.entity.MerchantPledgeTaskConf;
import com.sc.nft.entity.vo.IncomeRecordPageVO;
import com.sc.nft.entity.vo.merchantPledgeTask.*;
import com.sc.nft.entity.UserInfo;
import com.sc.nft.enums.MerchantPledgeTaskExamineStatusEnum;
import com.sc.nft.enums.RedisKeyEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.pool.UserPool;
import com.sc.nft.service.MerchantPledgeTaskConfService;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.sup.PageRequest;
import com.sc.nft.sup.PageResult;
import com.sc.nft.sup.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/merchant/pledge")
@Api(tags = "商户质押活动")
public class MerchantPledgeTaskController {

    private final MerchantPledgeTaskConfService merchantPledgeTaskConfService;
    private final MerchantPledgeTaskConfDao merchantPledgeTaskConfDao;
    private final Redisson redisson;

    @ApiOperation(value = "获取质押任务列表", notes = "获取质押任务列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getTaskPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<MerchantPledgeTaskPageVO> getTaskPage(@Valid @RequestBody MerchantPledgeTaskPageRequest request)  {
        return PageResult.success(merchantPledgeTaskConfService.getTaskPage(request.getDaoId(),request.getPageNo(),request.getPageSize()));
    }


    @ApiOperation(value = "获取质押任务详情", notes = "获取质押任务详情", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getTaskDetails", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<GetTaskDetailsVO> getTaskDetails(@Valid @RequestBody IdRequest request)  {
        return Result.success(merchantPledgeTaskConfService.getTaskDetails(UserPool.getUser(),request.getId()));
    }


    @ApiOperation(value = "是否可以满足质押条件", notes = "是否可以满足质押条件", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/isPledgeConditions", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<IsPledgeConditionsVO> isPledgeConditions(@Valid @RequestBody IsPledgeConditionsRequest request)  {
        return Result.success(new IsPledgeConditionsVO(merchantPledgeTaskConfService.isPledgeConditions(UserPool.getUser(),request.getId(),request.getCycleConfid(),request.getCount(),request.getPledeCollectionList())));
    }


    @ApiOperation(value = "质押藏品", notes = "质押藏品", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/pledgeCollection", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result pledgeCollection(@Valid @RequestBody PledgeCollectionRequest request)  {

        UserInfo user = UserPool.getUser();
        if(!StrUtil.equals(request.getDealPwd(),user.getTransactionPassword())){
            return Result.fail(ErrorCode.PASSWORD_ERROR);
        }

        MerchantPledgeTaskConf pledgeTaskConf = merchantPledgeTaskConfDao.getById(request.getId());
        Assert.notNull(pledgeTaskConf,()->new GlobalRunTimeException("该质押任务不存在"));
        Assert.isTrue(pledgeTaskConf.getIsListing(),()->new GlobalRunTimeException("该质押任务已下架"));
        Assert.isTrue(pledgeTaskConf.getExamineStatus() == MerchantPledgeTaskExamineStatusEnum.AUDIT_SUCCESS,()->new GlobalRunTimeException("该质押任务已下架"));


        RLock lock = redisson.getLock(RedisKeyEnum.MERCHANT_PLEDGE_COLLECTION_SECRET_AREA_LOCK.getKey() + pledgeTaskConf.getId());
        RLock userLock = redisson.getLock(RedisKeyEnum.USER_MERCHANT_PLEDGE_COLLECTION_SECRET_AREA_LOCK.getKey() + user.getId());
        try {
            boolean res = lock.tryLock(10, TimeUnit.SECONDS);
            if (res) {

                boolean userLockRes = userLock.tryLock(10, TimeUnit.SECONDS);

                if(!userLockRes){
                    return Result.fail("请稍后重试!");
                }
                merchantPledgeTaskConfService.pledgeCollection(user,pledgeTaskConf,request.getCycleConfid(),request.getCount(),request.getPledeCollectionList());
            }else{
                return Result.fail("请稍后重试!");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
            throw new GlobalRunTimeException("系统超时");
        } finally {
            lock.unlock();
            userLock.unlock();
        }
        return Result.success();
    }

    @ApiOperation(value = "挖宝记录", notes = "挖宝记录", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/treasureRecordPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<TreasureRecordPageVO> treasureRecordPage(@Valid @RequestBody PageRequest request)  {
        return PageResult.success(merchantPledgeTaskConfService.treasureRecordPage(UserPool.getUser(),request.getPageNo(),request.getPageSize()));
    }
    //挖宝详情
    @ApiOperation(value = "挖宝记录详情", notes = "挖宝记录详情", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/treasureRecordDetails", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<TreasureRecordDetailsVO> treasureRecordDetails(@Valid @RequestBody IdRequest request)  {
        return Result.success(merchantPledgeTaskConfService.treasureRecordDetails(UserPool.getUser(),request.getId()));
    }



    @ApiOperation(value = "收益记录", notes = "收益记录", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/incomeRecordPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<IncomeRecordPageVO> incomeRecordPage(@Valid @RequestBody PageRequest request)  {
        return PageResult.success(merchantPledgeTaskConfService.incomeRecordPage(UserPool.getUser(),request.getPageNo(),request.getPageSize()));
    }

    @ApiOperation(value = "收益记录详情", notes = "收益记录详情", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/incomeRecordDetails", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<List<MerchantPledgeCollectionRewardsVO>> incomeRecordDetails(@Valid @RequestBody IdRequest request)  {
        return Result.success(merchantPledgeTaskConfService.incomeRecordDetails(UserPool.getUser(),request.getId()));
    }

    @ApiOperation(value = "退出质押活动", notes = "退出质押活动", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/exitTask", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result exitTaskByUserRecorId(@Valid @RequestBody ExitTaskRequest request)  {
        UserInfo user = UserPool.getUser();
        if(!StrUtil.equals(request.getDealPwd(),user.getTransactionPassword())){
            return Result.fail(ErrorCode.PASSWORD_ERROR);
        }

        merchantPledgeTaskConfService.exitTaskByUserRecorId(user,request.getId());
        return Result.success();
    }

    @ApiOperation(value = "获取当前时间", notes = "获取当前时间", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/nowDate", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<Long> nowDate()  {
        Long nowDate = System.currentTimeMillis();
        return Result.success(nowDate);
    }
}
